/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ui;

import constants.StringConstants;
import exception.ApplicationException;
import exception.ModelException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Timer;
import java.util.TimerTask;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.TextField;
import javax.microedition.lcdui.Ticker;
import javax.microedition.midlet.*;

/**
 * @author cristian
 */
public abstract class CustomMIDlet extends MIDlet implements CommandListener {

    protected static final int DEFAULT_TIMEOUT = 2500;

    protected static final int srtConstraints = TextField.NON_PREDICTIVE | TextField.SENSITIVE | TextField.ANY;
    protected static final int intConstraints = TextField.NON_PREDICTIVE | TextField.SENSITIVE | TextField.NUMERIC;
    protected static final int passwdConstraints = TextField.NON_PREDICTIVE | TextField.SENSITIVE | TextField.ANY | TextField.PASSWORD;

    private Hashtable mapAppendedOptions = new Hashtable();

    protected Display display;
    protected Command cmdExit, cmdOk, cmdBack, cmdCancel;
    protected Alert altError, altMsg, altInfo, altException;
    protected FancyScreen altBusy;
    protected Ticker tkrPerformingOp;

    public CustomMIDlet() {
        display = Display.getDisplay(this);

        cmdExit = new Command(StringConstants.CMD_EXIT, Command.EXIT, 1);
        cmdOk = new Command(StringConstants.CMD_OK, Command.OK, 1);
        cmdBack = new Command(StringConstants.CMD_BACK, Command.BACK, 1);
        cmdCancel = new Command(StringConstants.CMD_CANCEL, Command.CANCEL, 1);

        altError = new Alert(StringConstants.ALT_ERROR_TITLE);
        altError.setType(AlertType.ERROR);
        altError.setTimeout(Alert.FOREVER);
        altError.setCommandListener(this);

        altException = new Alert(StringConstants.ALT_ERROR_TITLE);
        altException.setType(AlertType.ERROR);
        altException.setTimeout(DEFAULT_TIMEOUT);
        altException.setCommandListener(this);

        altMsg = new Alert(StringConstants.ALT_MSG);
        altMsg.setType(AlertType.CONFIRMATION);
        altMsg.setTimeout(DEFAULT_TIMEOUT);
        altMsg.setCommandListener(this);

        altInfo = new Alert(StringConstants.ALT_MSG);
        altInfo.setType(AlertType.INFO);
        altInfo.setTimeout(Alert.FOREVER);
        altInfo.setCommandListener(this);

        altBusy = new FancyScreen();
        altBusy.setCommandListener(this);

        tkrPerformingOp = new Ticker(StringConstants.TXT_PERFORMING_OP);        
    }

    public void reportAppException(ApplicationException ex) {
        switch(ex.getCode()) {
            case ApplicationException.RMS_PERSISTENCE_EXCEPTION:
                reportFatalException(StringConstants.ALT_PERSISTENCE_ERROR);
                break;
            case ApplicationException.HTTP_IO_EXCEPTION:
                reportException(StringConstants.ALT_IO_ERROR);
                break;
            default:
                String msg = ex.getMessage() == null ? ex.getClass().getName() : ex.getMessage();
                reportFatalException(msg);
        }
        
    }

    protected void reportFatalException(String ex) {
        if(ex != null && ex.length() > 0)
            altError.setString(ex);

        setView(altError);
    }

    protected void reportException(String ex) {
        if(ex != null && ex.length() > 0)
            altException.setString(ex);
        setView(altException);
    }

    public void showMsg(String text, Displayable nextScreen) {
        if(text != null && text.length() > 0)
            altMsg.setString(text);

        if(nextScreen == null)
            setView(altMsg);
        else
            display.setCurrent(altMsg, nextScreen);
    }

    public void showInfoMsg(String text) {
        if(text != null && text.length() > 0)
            altInfo.setString(text);
        setView(altInfo);
    }

    public void showBusyScreen(String text) {
        if(text != null && text.length() > 0)
            altBusy.setText(text);
        setView(altBusy);
    }

    protected void setView(Displayable d) {
        display.setCurrent(d);
    }

    protected void setView(Displayable dis, int timeout) {
        new Timer().schedule(new DelayedViewTimerTask(dis), timeout);
    }

    protected class DelayedViewTimerTask extends TimerTask {
        private Displayable dis;

        public DelayedViewTimerTask(Displayable d) {
            dis = d;
        }

        public void run() {
            setView(dis);
        }
    }

    protected void exitApp() {
        try {
            destroyApp(true);
        } catch (MIDletStateChangeException ex) {
            reportFatalException(StringConstants.EX_APP_COULD_NOT_BE_CLOSED);
        }
    }

    protected void addOption(List list, String option) {
        if (!mapAppendedOptions.containsKey(list)) {
            mapAppendedOptions.put(list, new Hashtable());
        }

        Hashtable options = (Hashtable) mapAppendedOptions.get(list);
        if (!options.containsKey(option)) {
            options.put(new Integer(list.append(option, null)), option);
        }
    }

    protected String getOption(List list, int selectedIndex) {
        if (!mapAppendedOptions.containsKey(list)) {
            return null;
        }

        Integer index = new Integer(selectedIndex);
        Hashtable options = (Hashtable) mapAppendedOptions.get(list);
        return options.containsKey(index) ? (String) options.get(index) : null;
    }

    protected boolean containsOption(List list, String option) {
        if (mapAppendedOptions.containsKey(list)) {
            Hashtable options = (Hashtable) mapAppendedOptions.get(list);
            Enumeration keys = options.keys();
            Integer key = null;
            while (keys.hasMoreElements()) {
                key = (Integer) keys.nextElement();
                if (options.get(key).equals(option)) {
                    return true;
                }
            }
        }
        return false;
    }

    protected void removeOption(List list, String option) {
        if (mapAppendedOptions.containsKey(list)) {
            Hashtable options = (Hashtable) mapAppendedOptions.get(list);
            Enumeration keys = options.keys();
            boolean found = false;
            Integer key = null;
            while (keys.hasMoreElements() && !found) {
                key = (Integer) keys.nextElement();
                if (options.get(key).equals(option)) {
                    found = true;
                }
            }
            if (found) {
                options.remove(key);
            }
        }
    }

    public void showMainScreen() {
        setView(getMainScreen());
    }

    protected void customizeUIElements() {};

    public abstract void reportModelException(ModelException ex);
    public abstract Displayable getMainScreen();    

}
